package com.gs.coursera.algorithms.core.graph;

import java.util.LinkedHashSet;
import java.util.Set;
/**
 * A vertex with its content. Can have weight.
 * A vertex may have its adjacency list.
 * @author Sabuj
 *
 * @param <T>
 * @param <W>
 */
public class Vertex<T , W extends Comparable<W>> {

	private int vertexNumber = 0;
	private final T value;
	private W weight;
	private Set<Edge<T, W>> adjacencyList;
	private boolean discovered = false;
	private boolean explored = false;
	
	
	/**
	 * Create a vertex with content.
	 * @param value
	 */
	public Vertex(T value) {
		this.value = value;
		adjacencyList = new LinkedHashSet<Edge<T,W>>();
	}
	
	/**
	 * Create a vertex with content and weight.
	 * @param value
	 * @param weight
	 */
	public Vertex(T value, W weight) {
		this(value);
		this.weight = weight;
	}

	public W getWeight() {
		return weight;
	}

	public void setWeight(W weight) {
		this.weight = weight;
	}

	public T getValue() {
		return value;
	}

	public Set<Edge<T, W>> getAdjacencyList() {
		return adjacencyList;
	}

	public boolean isDiscovered() {
		return discovered;
	}

	public void setDiscovered(boolean discovered) {
		this.discovered = discovered;
	}

	public int getVertexNumber() {
		return vertexNumber;
	}

	public void setVertexNumber(int vertexNumber) {
		this.vertexNumber = vertexNumber;
	}

	public boolean isExplored() {
		return explored;
	}

	public void setExplored(boolean explored) {
		this.explored = explored;
	}

	/**
	 * Add an edge to the adjacency list of this vertex.
	 * @param edge
	 */
	public void addAdjacentEdge(Edge<T, W> edge){
		if(null == edge 
				|| edge.getStartVertex() == null
				|| this != edge.getStartVertex())
			return;
		adjacencyList.add(edge);
	}
	
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((value == null) ? 0 : value.hashCode());
		return result;
	}

	/**
	 * 2 vertices are equal, if they have same content. Assuming that a 
	 * graph is having distinct vertices.
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof Vertex)) {
			return false;
		}
		Vertex other = (Vertex) obj;
		if (value == null) {
			if (other.value != null) {
				return false;
			}
		} else if (!value.equals(other.value)) {
			return false;
		}
		return true;
	}

	@Override
	public String toString() {
		return String.format("Vertex [%s]", vertexNumber);
	}

	
}
